﻿using UnityEngine;

// 该组件不允许在同一 GameObject 上多次添加
// 即一个 GameObject 上只能挂载一个 PerObjectMaterialProperties 组件
[DisallowMultipleComponent]
public class PerObjectMaterialProperties : MonoBehaviour
{
	// 定义 Shader 属性的名字对应的 ID，用于高效访问
	// 这些 ID 是通过 Shader.PropertyToID() 方法提前计算好的，比每次传字符串更高效
	static int baseColorId = Shader.PropertyToID("_BaseColor");  // 对应 Shader 中的 _BaseColor 属性
	static int cutoffId = Shader.PropertyToID("_Cutoff");        // 对应 Shader 中的 _Cutoff（通常是 AlphaCutOff）

	// MaterialPropertyBlock 是一种轻量级机制，用于在不创建新材质实例的情况下修改材质属性
	// 多个 Renderer 可以共享同一个材质，但通过 PropertyBlock 修改各自的属性表现
	static MaterialPropertyBlock block;

	// 序列化字段，在 Inspector 面板中可编辑
	[SerializeField]
	Color baseColor = Color.white;  // 基础颜色，默认为白色

	[SerializeField, Range(0f, 1f)]  // 限制范围在 0~1，适合用作 Alpha 阈值
	float alphaCutoff = 0.5f;        // Alpha 裁剪阈值，用于透明/遮罩效果

	/// <summary>
	/// Awake 生命周期方法，在对象初始化时调用一次
	/// 这里主动调用 OnValidate，确保一开始就应用属性
	/// </summary>
	void Awake()
	{
		OnValidate();
	}

	/// <summary>
	/// OnValidate 是 Unity 编辑器中独有的方法
	/// 当你在 Inspector 中修改了序列化字段（比如 baseColor 或 alphaCutoff）时自动调用
	/// 用于实时更新材质属性，方便在编辑模式下预览效果
	/// ⚠️ 注意：OnValidate 只在 Editor 模式下执行，不会在运行时（Build 后）触发
	/// </summary>
	void OnValidate()
	{
		// 如果 MaterialPropertyBlock 还没有初始化，则创建一个
		if (block == null)
		{
			block = new MaterialPropertyBlock();
		}

		// 使用 block 设置 Shader 属性值
		block.SetColor(baseColorId, baseColor);     // 设置基础颜色
		block.SetFloat(cutoffId, alphaCutoff);      // 设置 Alpha 裁剪阈值

		// 获取当前 GameObject 上的 Renderer 组件（比如 MeshRenderer 或 SkinnedMeshRenderer）
		// 并将这个 MaterialPropertyBlock 应用到该 Renderer 上
		GetComponent<Renderer>().SetPropertyBlock(block);
	}
}